home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / setscreen.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  517 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    setscreen - 
  19.  *        PostScript style halftoning stuff
  20.  *
  21.  *            Paul Haeberli - 1990
  22.  */
  23. #include "values.h"
  24. #include "math.h"
  25. #include "stdio.h"
  26. #include "setscreen.h"
  27.  
  28. #define MAXBMSIZE    (100000)
  29. #define PRINTRES    (300.0)
  30.  
  31. #define OCT0    0
  32. #define OCT1    1
  33.  
  34. static float *fbm;
  35. static int bm1size, bm2size;
  36.  
  37. static int cmpfunc(v0,v1)
  38. int *v0, *v1;
  39. {
  40.     if(fbm[*v0]<fbm[*v1])
  41.     return -1;
  42.     if(fbm[*v0]>fbm[*v1])
  43.     return 1;
  44.     return 0;
  45. }
  46.  
  47. float sampleproc(dx,dy,x,y,proc,rot90)
  48. int dx, dy;
  49. int x, y;
  50. float (*proc)();
  51. int rot90;
  52. {
  53.     float fx, fy, mag, temp;
  54.  
  55.     mag = bm1size+bm2size;
  56.     fx = (dy*(y+0.5)+dx*(x+0.5))/mag;
  57.     fy = (dy*(x+0.5)-dx*(y+0.5))/mag;
  58.  
  59.     fx = 2.0*fx-1.0;
  60.     fy = 2.0*fy-1.0;
  61.  
  62.     if(fx<-1.0)
  63.     fx += 2.0;
  64.     if(fy<-1.0)
  65.     fy += 2.0;
  66.     if(fx>1.0)
  67.     fx -= 2.0;
  68.     if(fy>1.0)
  69.     fy -= 2.0;
  70.     if(rot90>=2) {
  71.     fx = -fx;
  72.     fy = -fy;
  73.     rot90 -= 2;
  74.     }
  75.     if(rot90) {
  76.      temp = fx;
  77.     fx = fy;
  78.     fy = -temp;
  79.     }
  80.     return proc(fx,fy);
  81. }
  82.  
  83. static freescreeen(ht)
  84. halftone *ht;
  85. {
  86.     if(ht->bm) {
  87.     free(ht->bm);
  88.         free(ht->nexti);
  89.     }
  90.     free(ht);
  91. }
  92.  
  93. halftone *setscreen2(dx,dy,rot90,proc)
  94. int dx, dy, rot90;
  95. float (*proc)();
  96. {
  97.     int i, x, y, s, f, p;
  98.     int *order;
  99.     int totsize, w2;
  100.     int octant, base, mint, maxt;
  101.     unsigned char *bm;
  102.     int *nexti;
  103.     halftone *ht;
  104.  
  105.     if(dx<0 || dy<0) {
  106.     fprintf(stderr,"hway: screen too fine\n");
  107.     return 0;
  108.     }
  109.     if(dy>dx) 
  110.     octant = OCT0;
  111.     else
  112.     octant = OCT1;
  113.     bm1size = dy*dy;
  114.     bm2size = dx*dx;
  115.     totsize = bm1size+bm2size;
  116.     if(dy == 0)
  117.     return 0;
  118.     w2 = dx+dy;
  119.     if((totsize)>MAXBMSIZE) {
  120.     fprintf(stderr,"hway: screen too coarse\n");
  121.     return 0;
  122.     }
  123.     fbm = (float *)mymalloc(totsize*sizeof(float));
  124.     bm = (unsigned char *)mymalloc(totsize);
  125.     order = (int *)mymalloc(totsize*sizeof(int));
  126.     nexti = (int *)mymalloc(totsize*sizeof(int));
  127.     p = 0;
  128.  
  129.     ht = (halftone *)mymalloc(sizeof(halftone));
  130.     ht->angle = 0.0;        /* don't know */
  131.     ht->totsize = totsize;
  132.     ht->dx = dx;
  133.     ht->dy = dy;
  134.     ht->w2 = w2;
  135.     ht->octant = octant;
  136.     ht->bm = bm;
  137.     ht->nexti = nexti;
  138.  
  139.     if(octant == 0) {
  140.     base = dy*(dy-dx);
  141.     ht->base = base;
  142.     for(i=0; i<totsize; i++) {
  143.         if(i<base) {
  144.         x = i%dy;
  145.         y = i/dy;
  146.         } else {
  147.         x = (i-base)%w2;
  148.         y = (dy-dx)+(i-base)/w2;
  149.         }
  150.         fbm[i] = sampleproc(dx,dy,x,y,proc,rot90);
  151.         order[p++] = i;
  152.         nexti[i] = findhtindex(ht,x+1,y);
  153.     }
  154.     } else {
  155.     base = dx*(dx-dy);
  156.     ht->base = base;
  157.     for(i=0; i<totsize; i++) {
  158.         if(i<base) {
  159.         x = (i%dx)+dy;
  160.         y = (i/dx)-(dx-dy);
  161.         } else {
  162.         x = (i-base)%w2;
  163.         y = (i-base)/w2;
  164.         }
  165.         fbm[i] = sampleproc(dx,dy,x,y,proc,rot90);
  166.         order[p++] = i;
  167.         nexti[i] = findhtindex(ht,x+1,y);
  168.     }
  169.     }
  170.     qsort(order,totsize,sizeof(int),cmpfunc);
  171.     mint = 256;
  172.     maxt = 0;
  173.     s = 0;
  174.     for(i=0; i<256; i++) {
  175.     f = (i*totsize)/255;
  176.     while(s<f) {
  177.         p = order[s];
  178.         bm[p] = 255-i;
  179.         if(bm[p]==0)
  180.         bm[p] = 1;
  181.         if(bm[p]>maxt)
  182.         maxt = bm[p];
  183.         if(bm[p]<mint)
  184.         mint = bm[p];
  185.         s++;
  186.     }
  187.     }
  188.     free(order);
  189.     free(fbm);
  190.     ht->mint = mint;
  191.     ht->maxt = maxt;
  192.     return ht;
  193. }
  194.  
  195. /*
  196.  *    proc is called with values from -1 to 1 in u and v.
  197.  *
  198.  */
  199. halftone *setscreen(lines,angle,proc)
  200. float lines, angle;
  201. float (*proc)();
  202. {
  203.     int dx, dy, rot90;
  204.     float ang;
  205.     halftone *ht;
  206.  
  207.     ang = angle;
  208.     while(ang>360.0)
  209.     ang -= 360.0;
  210.     while(ang<0.0)
  211.     ang += 360.0;
  212.     rot90 = 0;
  213.     while(ang>=90.0) {
  214.     ang -= 90.0;
  215.     rot90++;
  216.     }
  217.     dx = ((PRINTRES/lines)*sin(M_PI*ang/180.0))+0.5;
  218.     dy = ((PRINTRES/lines)*cos(M_PI*ang/180.0))+0.5;
  219.     ht = setscreen2(dx,dy,rot90,proc);
  220.     ht->angle = angle;
  221.     return ht;
  222. }
  223.  
  224. screenrow(ht,buf,n,x,y)
  225. halftone *ht;
  226. short *buf;
  227. int n, y;
  228. {
  229.     int i;
  230.     unsigned char *bm;
  231.     int *nexti;
  232.  
  233.     i = findhtindex(ht,x,y);
  234.     bm = ht->bm;
  235.     nexti = ht->nexti;
  236.     while (n--) {
  237.     if(*buf>=bm[i])
  238.         *buf = 255;        
  239.     else
  240.        *buf = 0;        
  241.     i = nexti[i];
  242.     buf++;
  243.     x++;
  244.     }
  245. }
  246.  
  247. bmscreenrow(ht,buf,bits,n,x,y)
  248. halftone *ht;
  249. short *buf;
  250. unsigned char *bits;
  251. int n, y;
  252. {
  253.     int i;
  254.     unsigned char c, maskbit;
  255.     unsigned char *bm;
  256.     int *nexti;
  257.  
  258.     i = findhtindex(ht,x,y);
  259.     bm = ht->bm;
  260.     nexti = ht->nexti;
  261.     maskbit = 0x80;
  262.     c = 0;
  263.     while (n) {
  264.     if(n>=8) {
  265.         if(buf[0]<bm[i])
  266.         c  |= 0x80;
  267.         i = nexti[i];
  268.         if(buf[1]<bm[i])
  269.         c  |= 0x40;
  270.         i = nexti[i];
  271.         if(buf[2]<bm[i])
  272.         c  |= 0x20;
  273.         i = nexti[i];
  274.         if(buf[3]<bm[i])
  275.         c  |= 0x10;
  276.         i = nexti[i];
  277.         if(buf[4]<bm[i])
  278.         c  |= 0x08;
  279.         i = nexti[i];
  280.         if(buf[5]<bm[i])
  281.         c  |= 0x04;
  282.         i = nexti[i];
  283.         if(buf[6]<bm[i])
  284.         c  |= 0x02;
  285.         i = nexti[i];
  286.         if(buf[7]<bm[i])
  287.         c  |= 0x01;
  288.         i = nexti[i];
  289.         buf += 8;
  290.         *bits++ = c;
  291.         n -= 8;
  292.         c = 0;
  293.     } else {
  294.         if(*buf++<bm[i])
  295.         c |= maskbit;
  296.         n--;
  297.     }
  298.     }
  299.     if(maskbit != 0x80)
  300.     *bits++ = c;
  301. }
  302.  
  303. bmscreenlevel1(ht,level,bits,x,y)
  304. halftone *ht;
  305. unsigned char level;
  306. unsigned char *bits;
  307. int x, y;
  308. {
  309.     if(level>=ht->maxt)
  310.     *bits &= (0xff7f>>(x&7));
  311.     else if(level<ht->mint)
  312.     *bits |= (0x80>>(x&7));
  313.     else if(level<ht->bm[findhtindex(ht,x,y)])
  314.     *bits |= (0x80>>(x&7));
  315.     else
  316.     *bits &= (0xff7f>>(x&7));
  317. }
  318.  
  319. bmscreenlevel(ht,level,bits,n,x,y)
  320. halftone *ht;
  321. unsigned char level;
  322. unsigned char *bits;
  323. int n, x, y;
  324. {
  325.     int i, low;
  326.     unsigned char c, maskbit;
  327.     unsigned char *bm;
  328.     int *nexti;
  329.  
  330.     low = x&7;
  331.     if(level>=ht->maxt) {
  332.     if(low) {
  333.         if(n<=(8-low)) {
  334.         maskbit = (0xff>>low)&(0xff00>>(low+n));
  335.         *bits &= ~maskbit;
  336.         return;
  337.         }
  338.         n -= 8-low;
  339.         *bits++ &= ~(0x00ff>>low);
  340.     }
  341.     while (n>=64) {
  342.         *bits++ = 0x00;
  343.         *bits++ = 0x00;
  344.         *bits++ = 0x00;
  345.         *bits++ = 0x00;
  346.         *bits++ = 0x00;
  347.         *bits++ = 0x00;
  348.         *bits++ = 0x00;
  349.         *bits++ = 0x00;
  350.         n -= 64;
  351.     }
  352.     while (n>=8) {
  353.         *bits++ = 0x00;
  354.         n -= 8;
  355.     }
  356.     if(n>0) 
  357.         *bits &= (0x00ff>>n);
  358.     return;
  359.     } else if(level<ht->mint) {
  360.     if(low) {
  361.         if(n<=(8-low)) {
  362.         maskbit = (0xff>>low)&(0xff00>>(low+n));
  363.         *bits |= maskbit;
  364.         return;
  365.         }
  366.         n -= 8-low;
  367.         *bits++ |= (0x00ff>>low);
  368.     }
  369.     while (n>=64) {
  370.         *bits++ = 0xff;
  371.         *bits++ = 0xff;
  372.         *bits++ = 0xff;
  373.         *bits++ = 0xff;
  374.         *bits++ = 0xff;
  375.         *bits++ = 0xff;
  376.         *bits++ = 0xff;
  377.         *bits++ = 0xff;
  378.         n -= 64;
  379.     }
  380.     while (n>=8) {
  381.         *bits++ = 0xff;
  382.         n -= 8;
  383.     }
  384.     if(n>0) 
  385.         *bits |= (0xff00>>n);
  386.     return;
  387.     }
  388.     i = findhtindex(ht,x,y);
  389.     bm = ht->bm;
  390.     nexti = ht->nexti;
  391.     if(low) {
  392.     c = *bits;
  393.     maskbit = 0x80>>low;
  394.     while(n) {
  395.         if(level<bm[i])
  396.         c |= maskbit;
  397.         else
  398.         c &= ~maskbit;
  399.         i = nexti[i];
  400.         maskbit >>= 1;
  401.         n--;
  402.         if(maskbit == 0)
  403.            break;
  404.     }
  405.     *bits++ = c;
  406.     }
  407.     while (n>=8) {
  408.     c = 0;
  409.     if(level<bm[i])
  410.         c  |= 0x80;
  411.     i = nexti[i];
  412.     if(level<bm[i])
  413.         c  |= 0x40;
  414.     i = nexti[i];
  415.     if(level<bm[i])
  416.         c  |= 0x20;
  417.     i = nexti[i];
  418.     if(level<bm[i])
  419.         c  |= 0x10;
  420.     i = nexti[i];
  421.     if(level<bm[i])
  422.         c  |= 0x08;
  423.     i = nexti[i];
  424.     if(level<bm[i])
  425.         c  |= 0x04;
  426.     i = nexti[i];
  427.     if(level<bm[i])
  428.         c  |= 0x02;
  429.     i = nexti[i];
  430.     if(level<bm[i])
  431.         c  |= 0x01;
  432.     i = nexti[i];
  433.     *bits++ = c;
  434.     n -= 8;
  435.     } 
  436.     if(n>0) {
  437.     c = *bits;
  438.     maskbit = 0x80;
  439.     while (n) {
  440.         if(level<bm[i])
  441.         c |= maskbit;
  442.         else
  443.         c &= ~maskbit;
  444.         i = nexti[i];
  445.         maskbit >>= 1;
  446.         n--;
  447.     }
  448.     *bits = c;
  449.     }
  450. }
  451.  
  452. printht(ht)
  453. halftone *ht;
  454. {
  455.     float aa;
  456.     int start, repn;
  457.  
  458.     aa = (180.0/M_PI)*atan2((float)ht->dy,(float)ht->dx);
  459.     printf("angle requested: %f  actual angle: %f\n",ht->angle,aa);
  460.     printf("dx: %d dy: %d totsize: %d\n",ht->dx,ht->dy,ht->totsize);
  461.     repn = 0;
  462.     start = findhtindex(ht,0,0);
  463.     repn++;
  464.     while(findhtindex(ht,repn,0) != start)
  465.     repn++;
  466.     printf("cell size is %d by %d or %d area\n",repn,repn,repn*repn);
  467. }
  468.  
  469. int findhtindex(ht,x,y)
  470. halftone *ht;
  471. int x, y;
  472. {
  473.     int nx, ny;
  474.     int sx, sy;
  475.     int bign, bigmag;
  476.     int dx, dy;
  477.  
  478.     dx = ht->dx;
  479.     dy = ht->dy;
  480.     bign = 0x4000000/ht->totsize;
  481.     bigmag = bign*ht->totsize;
  482.     nx = (bigmag+dx*x+dy*y)/ht->totsize;
  483.     nx -= bign;
  484.     ny = (bigmag+dy*x-dx*y)/ht->totsize;
  485.     ny -= bign;
  486.  
  487.     x = x-nx*dx-ny*dy;
  488.     y = y-nx*dy+ny*dx;
  489.     if(x<dy) {
  490.     if(y<0) {
  491.         x = x+dx;
  492.         y = y+dy;
  493.     }
  494.     } else {
  495.     if(y<(dy-dx)) {
  496.         x = x-dy;
  497.         y = y+dx;
  498.     }
  499.     }
  500.     if(ht->octant == 0) {
  501.     if(y<(dy-dx)) {
  502.         return y*dy+x;
  503.     } else  {
  504.         y = y-(dy-dx);
  505.         return ht->base+y*ht->w2+x;
  506.     }
  507.     } else {
  508.     if(y>=0) {
  509.         return ht->base+y*ht->w2+x;
  510.     } else  {
  511.         x = x-dy;
  512.         y = y+(dx-dy);
  513.         return y*dx+x;
  514.     }
  515.     }
  516. }
  517.